//
// Created by Martin on 2023/2/10.
//

#include "IoFile.h"
#include "OsFile.h"

namespace ftp {
namespace filesystem {

//-----------------------------------------------------------------
// IoFileStream class implementation

IoFileStream::IoFileStream(const std::string &pathname, std::ios::openmode mode)
: path_(pathname)
{
    FileStatus_t status(kFileStatusIdle);
    if (mode & std::ios::in) {
        status = kFileStatusRead;
    }
    else if (mode & std::ios::out) {
        status = kFileStatusWrite;
    }

    lockFile_ = OSFileInstance.allocFile(pathname, status);
    if (lockFile_) {
        // create file if not exist when mode is writing file
        stream_.reset(new std::fstream(pathname, mode));
    }
}

IoFileStream::~IoFileStream()
{
    if (lockFile_)
        OSFileInstance.freeFile(path_);
}

void IoFileStream::read(char *buf, ssize_t size)
{
    if (stream_)
        stream_->read(buf, size);
}

void IoFileStream::write(const char* buf, ssize_t size)
{
    if (stream_)
        stream_->write(buf, size);
}

void IoFileStream::close()
{
    if (stream_)
        stream_->close();
}

void IoFileStream::flush()
{
    if (stream_)
        stream_->flush();
}

bool IoFileStream::good()
{
    return stream_ && stream_->good();
}

bool IoFileStream::eof()
{
    return stream_ && stream_->eof();
}

bool IoFileStream::fail()
{
    return stream_ && stream_->fail();
}

bool IoFileStream::is_open()
{
    return stream_ && stream_->is_open();
}

ssize_t IoFileStream::gcount()
{
    if (stream_)
        return stream_->gcount();
    return 0;
}

void IoFileStream::seekg(ssize_t pos)
{
    if (stream_)
        stream_->seekg(pos);
}

void IoFileStream::seekg(ssize_t offset, std::ios_base::seekdir dir)
{
    if (stream_)
        stream_->seekg(offset, dir);
}

void IoFileStream::setBuffer(std::vector<char> &buffer)
{
    if (!buffer.empty()) {
        if (stream_)
            stream_->rdbuf()->pubsetbuf(&buffer[0], static_cast<long>(buffer.size()));
    }
}

} // namespace filesystem
} // namespace ftp
